#include "protocol.h"
#include "command.h"
#include "serial.h"
#include "codec.h"
#include "bsp/uart.h"
#include "os/os.h"

static serial_t g_serial;

static void package_process(head_t *head, u8 *data, int len);

void handle_serial_frame(uint8_t *data, int len) {
    if (len >= sizeof(head_t)) {
        head_t *head = (head_t*)data;
        if (head->version != PROT_VERSION_0) {
            return;
        }
        int data_len = len - sizeof(head_t);
        if (data_len > 0) {
            data += sizeof(head_t);
        }else {
            data = NULL;
        }
        package_process(head, data, data_len);
    }
}

void protocol_init(void) {
	command_package_init();
    g_serial.rate = 500000;
    g_serial.rx_handler = handle_serial_frame;
    serial_init(&g_serial);
}

static void package_process(head_t *head, u8 *data, int len) {
    package_t pack;
    pack.command = head->command;
    pack.len = len;
    pack.type = head->type;
    if (len > 0) {
        pack.data = os_alloc(len);
        if (pack.data == NULL) {
            return;
        }
        memcpy(pack.data, data, len);
    }
    if (pack.command >= 0xF0) {
#ifndef USE_MEX_CMD
        process_iap_package(&pack);
#endif
        if (pack.data){
            os_free(pack.data);
        }
    }else {
        if(!process_command_package(&pack)){
            if (pack.data){
                os_free(pack.data);
            }
        }
    }
}

void protocol_send_package(head_t *head, u8 *data, int len) {
    int head_len = (head==NULL)?0:sizeof(head_t);
    serial_send_frame(&g_serial, (u8 *)head, head_len, data, len);
}

void protocol_send_ack(package_t *pack, u8 success) {
    head_t head;
    head.version = PROT_VERSION_0;
    head.command = pack->command;
    head.type = PROT_TYPE_ACK;
	protocol_send_package(&head, &success, 1);
}

void protocol_send_indicator(u8 command, u8 *data, int len) {
    head_t head;
    head.version = PROT_VERSION_0;
    head.command = command;
    head.type = PROT_TYPE_INDICAT;
    protocol_send_package(&head, data, len);
}


void protocol_send_response(u8 command, u8 *data, int len) {
    head_t head;
    head.version = PROT_VERSION_0;
    head.command = command;
    head.type = PROT_TYPE_ACK;
    protocol_send_package(&head, data, len);
}

